#include "delaunay.h"
#include "iostream"
#include "fstream"
#include "iomanip"

int main(int argc, char const *argv[])
{

	std::vector<vertex2dc> points(21);
	points[0].set(-0.8, -0.8, 0);
	points[1].set(0.4, -1.2, 1);
	points[2].set(1.2, -0.9, 2);
	points[3].set(1.6, 0.1, 3);
	points[4].set(2.5, 0.5, 4);
	points[5].set(4.1, 0.7, 5);
	points[6].set(5.7, 1.8, 6);
	points[7].set(5.1, 3.4, 7);
	points[8].set(2.5, 4.4, 8);
	points[9].set(1.2, 3.7, 9);
	points[10].set(-1.2, 3.9, 10);
	points[11].set(-3.2, 5.1, 11);
	points[12].set(-4.3, 2.9, 12);
	points[13].set(-3.1, 0.7, 13);
	points[14].set(-1.3, 0.6, 14);
	points[15].set(-2.1, 2.9, 15);
	points[16].set(0.6, 1.2, 16);
	points[17].set(0.1, 2.4, 17);
	points[18].set(2.4, 2.8, 18);
	points[19].set(3.5, 1.8, 19);
	points[20].set(3.6, 3.1, 20);

	/*
	std::vector<vertex2dc> points(21);
	points[0].set(-0.8, -0.8, 4);
	points[1].set(0.4, -1.2, 5);
	points[2].set(1.2, -0.9, 6);
	points[3].set(1.6, 0.1, 7);
	points[4].set(2.5, 0.5, 8);
	points[5].set(4.1, 0.7, 9);
	points[6].set(5.7, 1.8, 10);
	points[7].set(5.1, 3.4, 11);
	points[8].set(2.5, 4.4, 12);
	points[9].set(1.2, 3.7, 13);
	points[10].set(-1.2, 3.9, 14);
	points[11].set(-3.2, 5.1, 15);
	points[12].set(-4.3, 2.9, 16);
	points[13].set(-3.1, 0.7, 17);
	points[14].set(-1.3, 0.6, 18);
	points[15].set(-2.1, 2.9, 19);
	points[16].set(0.6, 1.2, 20);
	points[17].set(0.1, 2.4, 21);
	points[18].set(2.4, 2.8, 22);
	points[19].set(3.5, 1.8, 23);
	points[20].set(3.6, 3.1, 24);
	*/

	if (duplicated_vertex(points))
	{
		std::cerr << "Duplicated vertice detected.\n";
		return 0;
	}

	std::vector<triangle*> elements;
	triangulation(points, elements);

	if (fully_delaunay(elements, points))
	{
		std::clog << "The triangulation is fully delaunay.\n";
	}
	else std::clog << "The triangulation is not fully delaunay\n";

	// Write a Gmsh's .msh file
	std::ofstream outfile("demo.msh");
	outfile << "$MeshFormat" << std::endl << "2.2 0 8" << std::endl << "$EndMeshFormat "<<std::endl;
	outfile << "$Nodes" << std::endl << points.size() << std::endl;
	for (int i = 0; i < points.size(); i++)
	{
		outfile << points[i].id + 1 << " " << std::setprecision(16) 
			<< points[i].x << " " << points[i].y << " 0.0" << std::endl;
	}
	outfile<<"$EndNodes"<<std::endl;
	outfile << "$Elements" << std::endl << elements.size() <<std::endl;
	for (int i = 0; i < elements.size(); i++)
	{
		outfile << i + 1 << " 2 0";
		for (int j = 0; j < 3; j++)
		{
			outfile << " " << elements[i]->vert[j]->id + 1;
		}
		outfile << std::endl;
	}
	outfile << "$EndElements"<< std::endl;
	outfile.close();

	// write a neighbor file
	outfile.open("demo.neigh");
	outfile << elements.size() << std::endl;
	for (int i = 0; i < elements.size(); i++)
	{
		outfile << i + 1;
		for (int j = 0; j < 3; j++)
		{
			if (elements[i]->neigh[j] != nullptr)
			{
				outfile << " " << elements[i]->neigh[j]->id + 1;
			}
			else outfile << " -1";
		}
		outfile << std::endl;
	}
	outfile.close();

	// destroy allocated memories
	for (int i = 0; i < elements.size(); i++)
	{
		delete elements[i];
	}
	return 0;
}
